package com.java.star.mall.front.util;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * 微信签名工具类
 */
public class WxSigUtils {

    /**
     * 微信地图签名计算
     *
     * @param url        请求地址
     * @param secretKey  密钥
     * @param requestObj 请求参数
     * @param <T>        请求参数类型任意
     * @return 加密后的签名字符串
     * @throws URISyntaxException url地址解析异常
     */
    public static <T> String wxMapSig(String url, String secretKey, T requestObj) throws URISyntaxException {
        //排序请求参数
        String params = sortParam(requestObj);
        //获取请求路径的URI部分
        URI uri = new URI(url);
        //用请求路径的URI参数 + 请求参数 + 微信地图授权secret-key 进行MD5加密计算签名
        return DigestUtil.md5Hex(uri.getPath() + "?" + params + secretKey);
    }

    /**
     * 微信支付签名计算
     *
     * @param secretKey  商户密钥
     * @param requestObj 请求参数
     * @param <T>        请求参数类型任意
     * @return 加密后的签名字符串
     */
    public static <T> String wxPaySig(String secretKey, T requestObj) {
        //排序请求参数
        String params = sortParam(requestObj);
        //将请求参数拼接上商户密钥
        String stringSignTemp = params + "&key=" + secretKey;
        System.out.println(stringSignTemp);
        //计算MD5并转换为全大写字符串
        return DigestUtil.md5Hex(stringSignTemp).toUpperCase();
    }

    /**
     * 排序构建签名参数
     *
     * @param requestObj 参数对象
     * @return 构建好的参数
     */
    private static <T> String sortParam(T requestObj) {
        JSONObject params = requestObj instanceof JSONObject ? (JSONObject) requestObj
                : JSONObject.parseObject(JSON.toJSONString(requestObj));
        String[] keyArray = params.keySet().toArray(new String[params.keySet().size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if ("sign".equals(k)) {
                continue;
            }
            //参数值为空，则不参与签名
            if (params.get(k) != null) {
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(k).append("=").append(params.get(k));
            }
        }
        return sb.toString();
    }
}
